/*************************************************************************
 * Filename:    ProcessManager.h
 * Description: A process manager. Controls the transitions between 
 *              different states.
 * Group 2:     nachOS
 * Authors:     Ying Wang
 *              Daniel Fairweather
 *              Jan Durakiewicz
 * Class:       CSE 325
 * Instructor:  Mr. Duggan
 * Assignment:  Lab #3 Scheduler
 * Assigned:    Feburary 12, 2013
 * Due:         Feburary 26, 2013
 *************************************************************************/
#ifndef PROCESSMANAGER_H
#define PROCESSMANAGER_H

#define NUM_REGS 3
#define FREE_SPACE 100
#ifndef NULL
#define NULL 0
#define MAX_PID 2147483647
#endif



/**
 * The following numbers should be used to identify schedulers.
 * 0 Fair-share group scheduler 
 * 1 Priority-based scheduler
 */



/**
 * A process control block.
 */
typedef struct process_control_block_s{
    int pid;                                    /* The process id. */
    int gid;                                    /* The process group ID */
    int age;                                    /* The process' age */
    int psw;                                    /* The program status word. */
	int mailbox;                                /* The mailbox id. */
    int page_table;                             /* The page table. */
    int regs[NUM_REGS];                         /* An array of registers. */
    struct process_control_block_s* next;       /* The next process_control_block in the queue. */
    struct process_control_block_s* previous;   /* The previous process_control_block in the queue. */
} process_control_block;



/**
 * A freelist.
 */
typedef struct freelist_s{
    int length;                                          /* The length of the freelist. */
    struct process_control_block_s list[FREE_SPACE];     /* The storage array of the freelist. */
    struct process_control_block_s* head;                /* The pointer to the oldest process_control_block in the freelist. */
    struct process_control_block_s* tail;                /* The pointer to the newest process_control_block in the freelist. */
} freelist;



int scheduler_algorithm;                /* The scheduler currently being used. */
process_control_block* next_process;    /* The next scheduled process. */ 



/**
 * Initializes the freelist and all other queues.
 * @author Ying Wang
 * @params scheduler The id of the scheduler to be used.
 * @returns void.
 */
void initializeProcessManager(int scheduler);



/**
 * Creates a new PCB and adds it to the NEW queue.
 * @author Daniel Fairweather
 * @param pid The process id.
 * @param psw The program status word.
 * @param page_table The page table.
 * @param regs An array of registers.
 * @returns process_control_block* The process control block that was created.
 */
process_control_block* create(int pid, int gid, int psw, int page_table, int regs[NUM_REGS]);



/**
 * Gets a process_control_block from the freelist.
 * @author Ying Wang
 * @returns process_control_block* the process_control_block that can be used.
 */
process_control_block* getPCB();



/**
 * Appends the process_control_block to the tail of the freelist.
 * @author Ying Wang
 * @param The process to free.
 * @returns void.
 */
void freePCB(process_control_block* target);



/**
 * The transition between New and Ready states.
 * @author Ying Wang
 * @returns process_control_block* the process_control_block that was transited.
 */
process_control_block* pReady();



/**
 * The transition between Ready and Running states.
 * @author Ying Wang
 * @returns process_control_block* the process_control_block that was transited.
 */
process_control_block* go();



/**
 * The transition between Running and Ready states.
 * @author Ying Wang
 * @returns process_control_block* the process_control_block that was transited.
 */
process_control_block* eoQuantum();



/**
 * The transition between Running and Waiting states.
 * @author Ying Wang
 * @returns process_control_block* the process_control_block that was transited.
 */
process_control_block* wait();



/**
 * The transition between Waiting and Ready states.
 * @author Ying Wang
 * @param The pid of the target process.
 * @returns process_control_block* the process_control_block that was transited.
 */
process_control_block* unwait(int pid);



/**
 * The transition between Running and Terminated states.
 * @author Ying Wang
 * @returns process_control_block* the process_control_block that was transited.
 */
process_control_block* eoLife();



/**
 * The transition between Waiting/Ready and Terminated states.
 * @author Ying Wang
 * @param The pid of the target process.
 * @returns process_control_block* the process_control_block that was transited.
 */
process_control_block* terminate(int pid);



/**
 * Schedules a process based on the fair-share group algorithm.
 * @author Jan Durakiewicz
 * @returns pcb pointer
 */
process_control_block* schedule_fs();



/**
 * Schedules a process based on the priority-based algorithm.
 * @author Ying Wang
 * @param The flag to indicate if all the processes should age at this point, 0 for no and 1 for yes.
 * @returns process_control_block* the process_control_block that was scheduled for the next round.
 */
process_control_block* schedule_pr(int flag);



/**
 * Gets an avialable PID in the range of 0 to MAX_PID.
 * @author Ying Wang
 * @returns int the unique PID that can be used.
 */
int getUniquePID();



/**
 * Sets the new priority of the pcb.
 * @author Ying Wang
 * @param The pointer of the pcb.
 * @returns int >=0 if the new priority is set, 
            -1 if the pointer is null (pcb doesn't exist), 
            -2 if the new priority is not valid.
 */
int setPriority(process_control_block* pcb, int priority);

#endif